home *** CD-ROM | disk | FTP | other *** search
Wrap
/* * SFskyedit - Star Fighter 3000 sky colours editor * Utility functions * Copyright (C) 2001 Chris Bazley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public Licence as published by * the Free Software Foundation; either version 2 of the Licence, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public Licence for more details. * * You should have received a copy of the GNU General Public Licence * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ANSI library files */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <stdbool.h> #include <limits.h> /* RISC OS library files */ #include "kernel.h" #include "toolbox.h" #include "event.h" #include "window.h" #include "wimplib.h" #include "wimp.h" #include "gadgets.h" #include "swis.h" #include "flex.h" /* My library files */ #include "ViewsMenu.h" #include "err.h" #include "msgtrans.h" #include "hourglass.h" #include "Macros.h" #include "SFformats.h" #include "FilePerc.h" /* Local headers */ #include "Utils.h" #include "Main.h" #define Wimp_ReportError_UseCategory (1u << 8) #define Wimp_ReportError_CatInform (1u << 9) #define Wimp_ReportError_CatWarning (2u << 9) #define Wimp_ReportError_CatProgram (3u << 9) #define Wimp_ReportError_CatQuestion (4u << 9) #ifdef INT_COLOUR_FIND /* OS 2 ColourTrans used R2,G3,B1 and OS 3 ColourTrans uses R2,G4,B1 */ #define RED_WEIGHT 2 #define GREEN_WEIGHT 4 #define BLUE_WEIGHT 1 #define SQUARE(n) ((n)*(n)) #endif /* ----------------------------------------------------------------------- */ /* Public functions */ bool verify_sky_file(SF_SkyColours **sky) { unsigned int *data = (*sky)->shade; int numsame, row; unsigned int band, oldband; if(!format_warning) return true; /* 1st row should be 2nd row dithered with itself */ if(data[0] != data[1]) goto badfile; numsame = 1; oldband = data[1]; /* kludge as 1st row should be dithered but can't be */ for(row = 2;row < 126;row++) { band = data[row]; /* check that 1st = 3rd and 2nd = 4th pixel */ if((band & 0x000000ff) != ((band & 0x00ff0000) >> 16) || ((band & 0x0000ff00) >> 8) != ((band & 0xff000000) >> 24)) goto badfile; /* check that band dithered with previous band */ if( (band & 0x00ff00ff) != (oldband & 0x00ff00ff) && (band & 0xff00ff00) != (oldband & 0xff00ff00) ) goto badfile; if(band == oldband) numsame++; else { if((oldband & 0xff) != ((oldband & 0xff00) >> 8)) { /* check that dithered section was 1 wide */ if(numsame>1) goto badfile; } else { /* check that width of plain section is odd number */ if((numsame & 1) != 1) goto badfile; } numsame = 1; } oldband = band; } return true; /* verified OK */ badfile: /* Bad format */ { int button; WRITE_ERR(shared_err_block, "DithWarn"); if(wimp_version >= 321) { /* Nice error box */ button = wimp_report_error(&shared_err_block, Wimp_ReportError_OK|Wimp_ReportError_Cancel|Wimp_ReportError_UseCategory|Wimp_ReportError_CatInform, taskname, NULL, NULL, msgs_lookup("DithQuiet")); } else { /* Backwards compatibility */ button = wimp_report_error(&shared_err_block, Wimp_ReportError_OK|Wimp_ReportError_Cancel, taskname); } switch(button) { case 3: /* shut up & continue */ format_warning = false; case Wimp_ReportError_OK: /* continue */ return true; } } return false; } /* ----------------------------------------------------------------------- */ int absdiff(int a, int b) { int c = a - b; if(c < 0) return -c; return c; } /* ----------------------------------------------------------------------- */ char brightness_of_24bit_col(unsigned int colour) { int r,g,b; r = (colour & 0x0000ff00) >> 8; g = (colour & 0x00ff0000) >> 16; b = (colour & 0xff000000) >> 24; /* CIE luminance weights for red, green and blue (0.299, 0.587, 0.114), which is the standard conversion for broadcast television */ return (char)((int)(0.299*(float)r) + (int)(0.587*(float)g) + (int)(0.114*(float)b)); } /* ----------------------------------------------------------------------- */ _kernel_oserror *open_topleftofwin(unsigned int flags, ObjectId showobj, ObjectId relativeto, ObjectId parent, ComponentId parent_component) { WimpGetWindowStateBlock winstate; WindowShowObjectBlock showblock; THROW(window_get_wimp_handle(0, relativeto, &(winstate.window_handle))) THROW(wimp_get_window_state(&winstate)) showblock.visible_area.xmin = winstate.visible_area.xmin+64; showblock.visible_area.ymin = winstate.visible_area.ymax-64; unsigned int state; THROW(toolbox_get_object_state(0, showobj, &state)) if(FLAG_SET(state, Toolbox_GetObjectState_Showing)) /* Already open (may be iconised) */ return ViewsMenu_show_object(flags, showobj, Toolbox_ShowObject_TopLeft, &showblock, parent, parent_component); else /* Not open (can't very well be iconised!) */ return toolbox_show_object(flags, showobj, Toolbox_ShowObject_TopLeft, &showblock, parent, parent_component); } /* ----------------------------------------------------------------------- */ _kernel_oserror *show_win_at_ptr(unsigned int flags, ObjectId id, ObjectId parent, ComponentId parent_component) { unsigned int state; THROW(toolbox_get_object_state(0, id, &state)) if(FLAG_SET(state, Toolbox_GetObjectState_Showing)) /* Already open (may be iconised) */ THROW(ViewsMenu_show_object(flags, id, Toolbox_ShowObject_Default, NULL, parent, parent_component)) else /* Not open (can't very well be iconised!) */ THROW(toolbox_show_object(flags, id, Toolbox_ShowObject_AtPointer, NULL, parent, parent_component)) return NULL; /* success */ } /* ----------------------------------------------------------------------- */ char *tail(char *pathname, int length) { char *ptr; int dotcount; ptr = (char *)((int)pathname + strlen(pathname)); /* terminator */ dotcount = 0; while(ptr > pathname && dotcount<length) { ptr--; /* scan string backwards from terminator */ if(*ptr == '.') dotcount++; } if(dotcount >= length) return (char *)((int)ptr + 1); return ptr; } /* ----------------------------------------------------------------------- */ char real_to_mode13col(unsigned int real_col) { /* Find nearest to ideal colour in default mode 13 palette */ #ifdef INT_COLOUR_FIND if(use_colour_trans) { #endif int nearest_colour; RE(_swix(ColourTrans_ReturnColourNumberForMode, _INR(0,2)|_OUT(0), real_col, 13, 0, &nearest_colour)) return nearest_colour; #ifdef INT_COLOUR_FIND } else { /* Like ColourTrans we use a least squares function, but we have control over the weights */ char best_col; unsigned int least_dist = UINT_MAX; int target_red = (real_col & 0xff00)>>8; int target_green = (real_col & 0xff0000)>>16; int target_blue = (real_col & 0xff000000)>>24; for(int colnum = 0; colnum <= 255; colnum++) { unsigned int dist = RED_WEIGHT*SQUARE(((palette[colnum] & 0xff00)>>8) - target_red) + GREEN_WEIGHT*SQUARE(((palette[colnum] & 0xff0000)>>16) - target_green) + BLUE_WEIGHT*SQUARE(((palette[colnum] & 0xff000000)>>24) - target_blue); if(dist < least_dist) { #ifndef NDEBUG {char string[256]; sprintf(string, "report new best match (dist %u) is col %d (R=%d, G=%d, B=%d)",dist,colnum,((palette[colnum] & 0xff00)>>8),((palette[colnum] & 0xff0000)>>16),((palette[colnum] & 0xff000000)>>24)); _kernel_oscli(string); } #endif least_dist = dist; best_col = colnum; } #ifndef NDEBUG else if(dist < least_dist*2) { char string[256]; sprintf(string, "report discounting col %d at dist of %u (R=%d, G=%d, B=%d)",colnum, dist,((palette[colnum] & 0xff00)>>8),((palette[colnum] & 0xff0000)>>16),((palette[colnum] & 0xff000000)>>24)); _kernel_oscli(string); } #endif } return best_col; } #endif } /* ----------------------------------------------------------------------- */ _kernel_oserror *setgadgetfaded(ObjectId window, ComponentId gadget, int flagval) { /* Set gadget to shaded/unshaded */ unsigned int flags; THROW(gadget_get_flags(0, window, gadget, &flags)) return gadget_set_flags(0, window, gadget, (flags & ~Gadget_Faded) | (Gadget_Faded * flagval)); } /* ----------------------------------------------------------------------- */ int watch_caret(int event_code, WimpPollBlock *event, IdBlock *id_block, void *handle) { switch(event_code) { case Wimp_ELoseCaret: *(bool *)handle = false; return 1; /* claim event */ case Wimp_EGainCaret: *(bool *)handle = true; return 1; /* claim event */ default: return 0; /* don't handle this event */ } } /* ----------------------------------------------------------------------- */ int hand_back_caret(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle) { /* Is our ancestor alive and not hidden? */ unsigned int anc_state; if(toolbox_get_object_state(0, id_block->ancestor_id, &anc_state) == NULL && FLAG_SET(anc_state, Toolbox_GetObjectState_Showing)) { /* Did we have the input focus? */ if(*(bool *)handle == true) { /* And is there now no input focus anywhere on the desktop? */ WimpGetCaretPositionBlock now_pos; if(!E(wimp_get_caret_position(&now_pos)) && now_pos.window_handle == -1) { /* OK, pass the focus back to ancestor window */ int window; if(!E(window_get_wimp_handle(0, id_block->ancestor_id, &window))) RE(wimp_set_caret_position(window, -1, 0, 0, -1, -1)) } } } return 0; /* pass event on */ } /* ----------------------------------------------------------------------- */ _kernel_oserror *hide_shared_if_child(ObjectId parent_id, ObjectId shared_id) { ObjectId ancestor; THROW(toolbox_get_ancestor(0, shared_id, &ancestor, NULL)) if(ancestor != parent_id) return NULL; return hide_deiconise(shared_id); } /* ----------------------------------------------------------------------- */ _kernel_oserror *hide_deiconise(ObjectId window) { unsigned int state; THROW(toolbox_get_object_state(0, window, &state)) if(!FLAG_SET(state, Toolbox_GetObjectState_Showing)) return NULL; /* nothing to do */ THROW(toolbox_hide_object(0, window)) /* Get wimp handle of underlying window */ WimpMessage msg_block; THROW(window_get_wimp_handle(0, window, &msg_block.data.words[0])) /* Broadcast message &400CB (window closed) in case it was iconised */ msg_block.hdr.size = sizeof(msg_block.hdr) + sizeof(int); msg_block.hdr.your_ref = 0; msg_block.hdr.action_code = Wimp_MWindowClosed; return wimp_send_message(Wimp_EUserMessage, &msg_block, 0, 0, NULL); } /* ----------------------------------------------------------------------- */ _kernel_oserror *load_compressed(char *filepath, flex_ptr buffer_anchor) { return perc_operation(FILEPERC_OP_DECOMP, filepath, 0, buffer_anchor); }